package temperature;
import static org.junit.Assert.*;

import java.math.BigDecimal;
import java.math.BigInteger;

import org.junit.*;


/**
 * Een testklasse voor de klasse Temperature.
 * 
 * 
 * @author Nathan Bekaert & Philippe de Potter de ten Broeck
 * @version 2.0
 */
public class TemperatureTest {

	static Temperature temp2000C;
	static Temperature temp2000K;
	static Temperature temp2000F;
	static Temperature temp0K;
	
	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
		temp2000C = new Temperature(new BigDecimal(BigInteger.valueOf(2000),0), TemperatureUnit.CELSIUS);
		temp2000K = new Temperature(new BigDecimal(BigInteger.valueOf(2000),0), TemperatureUnit.KELVIN);
		temp2000F = new Temperature(new BigDecimal(BigInteger.valueOf(2000),0), TemperatureUnit.FAHRENHEIT);
		temp0K = Temperature.KELVIN_0;
	}

	@AfterClass
	public static void tearDownAfterClass() throws Exception {
	}

	@Before
	public void setUp() throws Exception {
	}

	@After
	public void tearDown() throws Exception {
	}
	
	/**
	 * Testmethode voor initialisaties te controleren.
	 */
	@Test
	public void construct(){
		assertTrue(temp2000C.getTemperatureValueIn(TemperatureUnit.CELSIUS).compareTo(new BigDecimal(BigInteger.valueOf(2000),0)) == 0);
		assertTrue(temp2000C.getTemperatureValueIn(TemperatureUnit.KELVIN).compareTo(new BigDecimal(BigInteger.valueOf(227315),2)) == 0);
		assertTrue(temp2000C.getTemperatureValueIn(TemperatureUnit.FAHRENHEIT).compareTo(new BigDecimal(BigInteger.valueOf(3632),0)) == 0);
		
		assertTrue(temp2000K.getTemperatureValueIn(TemperatureUnit.CELSIUS).compareTo(new BigDecimal(BigInteger.valueOf(172685),2)) == 0);
		assertTrue(temp2000K.getTemperatureValueIn(TemperatureUnit.KELVIN).compareTo(new BigDecimal(BigInteger.valueOf(2000),0)) == 0);
		assertTrue(temp2000K.getTemperatureValueIn(TemperatureUnit.FAHRENHEIT).compareTo(new BigDecimal(BigInteger.valueOf(314033),2)) == 0);
		
		assertTrue(temp2000F.getTemperatureValueIn(TemperatureUnit.CELSIUS).compareTo(new BigDecimal(BigInteger.valueOf(109333),2)) == 0);
		assertTrue(temp2000F.getTemperatureValueIn(TemperatureUnit.KELVIN).compareTo(new BigDecimal(BigInteger.valueOf(136648),2)) == 0);
		assertTrue(temp2000F.getTemperatureValueIn(TemperatureUnit.FAHRENHEIT).compareTo(new BigDecimal(BigInteger.valueOf(2000),0)) == 0);
		
		assertTrue(temp0K.getTemperatureValueIn(TemperatureUnit.CELSIUS).compareTo(new BigDecimal(BigInteger.valueOf(27315),2).negate()) == 0);
		assertTrue(temp0K.getTemperatureValueIn(TemperatureUnit.KELVIN).compareTo(BigDecimal.ZERO) == 0);
		assertTrue(temp0K.getTemperatureValueIn(TemperatureUnit.FAHRENHEIT).compareTo(new BigDecimal(BigInteger.valueOf(45967),2).negate()) == 0);
	}
	
	/**
	 * Testmethode voor vele malen de omzetting tussen C en K.
	 */
	@Test
	public void multipleConversionsBetweenCandK(){
		Temperature temp1 = new Temperature(temp2000C.getTemperatureValueIn(TemperatureUnit.KELVIN), TemperatureUnit.KELVIN);
		Temperature temp2 = new Temperature(temp1.getTemperatureValueIn(TemperatureUnit.CELSIUS), TemperatureUnit.CELSIUS);
		for(int count = 0; count < 2000; count++){
			temp1 = new Temperature(temp2.getTemperatureValueIn(TemperatureUnit.KELVIN), TemperatureUnit.KELVIN);
			temp2 = new Temperature(temp1.getTemperatureValueIn(TemperatureUnit.CELSIUS), TemperatureUnit.CELSIUS);
		}
		assertEquals(temp2000C, temp1);
		assertEquals(temp2000C, temp2);
	}
	
	/**
	 * Testmethode voor vele malen de omzetting tussen C en F.
	 */
	@Test
	public void multipleConversionsBetweenCandF(){
		Temperature temp1 = new Temperature(temp2000C.getTemperatureValueIn(TemperatureUnit.FAHRENHEIT), TemperatureUnit.FAHRENHEIT);
		Temperature temp2 = new Temperature(temp1.getTemperatureValueIn(TemperatureUnit.CELSIUS), TemperatureUnit.CELSIUS);
		for(int count = 0; count < 2000; count++){
			temp1 = new Temperature(temp2.getTemperatureValueIn(TemperatureUnit.FAHRENHEIT), TemperatureUnit.FAHRENHEIT);
			temp2 = new Temperature(temp1.getTemperatureValueIn(TemperatureUnit.CELSIUS), TemperatureUnit.CELSIUS);
		}
		assertEquals(temp2000C, temp1);
		assertEquals(temp2000C, temp2);
	}
	
	/**
	 * Testmethode voor vele malen de omzetting tussen K en F.
	 */
	@Test
	public void multipleConversionsBetweenKandF(){
		Temperature temp1 = new Temperature(temp2000K.getTemperatureValueIn(TemperatureUnit.FAHRENHEIT), TemperatureUnit.FAHRENHEIT);
		Temperature temp2 = new Temperature(temp1.getTemperatureValueIn(TemperatureUnit.KELVIN), TemperatureUnit.KELVIN);
		for(int count = 0; count < 2000; count++){
			temp1 = new Temperature(temp2.getTemperatureValueIn(TemperatureUnit.FAHRENHEIT), TemperatureUnit.FAHRENHEIT);
			temp2 = new Temperature(temp1.getTemperatureValueIn(TemperatureUnit.KELVIN), TemperatureUnit.KELVIN);
		}
		assertEquals(temp2000K, temp1);
		assertEquals(temp2000K, temp2);
	}
	
	/**
	 * Testmethode voor vele malen de omzetting van C naar K naar F en terug naar C.
	 */
	@Test
	public void multipleConversionsFromCToKToFToC(){
		Temperature temp2 = new Temperature(temp2000C.getTemperatureValueIn(TemperatureUnit.KELVIN), TemperatureUnit.KELVIN);
		Temperature temp3 = new Temperature(temp2.getTemperatureValueIn(TemperatureUnit.FAHRENHEIT), TemperatureUnit.FAHRENHEIT);
		Temperature temp1 = new Temperature(temp3.getTemperatureValueIn(TemperatureUnit.CELSIUS), TemperatureUnit.CELSIUS);
		for(int count = 0; count < 2000; count++){
			temp2 = new Temperature(temp1.getTemperatureValueIn(TemperatureUnit.KELVIN), TemperatureUnit.KELVIN);
			temp3 = new Temperature(temp2.getTemperatureValueIn(TemperatureUnit.FAHRENHEIT), TemperatureUnit.FAHRENHEIT);
			temp1 = new Temperature(temp3.getTemperatureValueIn(TemperatureUnit.CELSIUS), TemperatureUnit.CELSIUS);
		}
		assertEquals(temp2000C, temp1);
		assertEquals(temp2000C, temp2);
		assertEquals(temp2000C, temp3);
	}
	
	/**
	 * Testmethode voor vele malen de omzetting van K naar C naar F en terug naar K.
	 */
	@Test
	public void multipleConversionsFromKToCToFToK(){
		Temperature temp2 = new Temperature(temp2000K.getTemperatureValueIn(TemperatureUnit.CELSIUS), TemperatureUnit.CELSIUS);
		Temperature temp3 = new Temperature(temp2.getTemperatureValueIn(TemperatureUnit.FAHRENHEIT), TemperatureUnit.FAHRENHEIT);
		Temperature temp1 = new Temperature(temp3.getTemperatureValueIn(TemperatureUnit.KELVIN), TemperatureUnit.KELVIN);
		for(int count = 0; count < 2000; count++){
			temp2 = new Temperature(temp1.getTemperatureValueIn(TemperatureUnit.CELSIUS), TemperatureUnit.CELSIUS);
			temp3 = new Temperature(temp2.getTemperatureValueIn(TemperatureUnit.FAHRENHEIT), TemperatureUnit.FAHRENHEIT);
			temp1 = new Temperature(temp3.getTemperatureValueIn(TemperatureUnit.KELVIN), TemperatureUnit.KELVIN);
		}
		assertEquals(temp2000K, temp1);
		assertEquals(temp2000K, temp2);
		assertEquals(temp2000K, temp3);
	}
	
	/**
	 * Testmethode voor vele malen de omzetting van F naar C naar K en terug naar F.
	 */
	@Test
	public void multipleConversionsFromFToCToKToF(){
		Temperature temp2 = new Temperature(temp2000F.getTemperatureValueIn(TemperatureUnit.CELSIUS), TemperatureUnit.CELSIUS);
		Temperature temp3 = new Temperature(temp2.getTemperatureValueIn(TemperatureUnit.KELVIN), TemperatureUnit.KELVIN);
		Temperature temp1 = new Temperature(temp3.getTemperatureValueIn(TemperatureUnit.FAHRENHEIT), TemperatureUnit.FAHRENHEIT);
		for(int count = 0; count < 2000; count++){
			temp2 = new Temperature(temp1.getTemperatureValueIn(TemperatureUnit.CELSIUS), TemperatureUnit.CELSIUS);
			temp3 = new Temperature(temp2.getTemperatureValueIn(TemperatureUnit.KELVIN), TemperatureUnit.KELVIN);
			temp1 = new Temperature(temp3.getTemperatureValueIn(TemperatureUnit.FAHRENHEIT), TemperatureUnit.FAHRENHEIT);
		}
		assertEquals(temp2000F, temp1);
		assertEquals(temp2000F, temp2);
		assertEquals(temp2000F, temp3);
	}
	
	/**
	 * Testmethode voor vele malen de omzetting van K naar F naar C en terug naar K.
	 */
	@Test
	public void multipleConversionsWithAbsoluteNul(){
		Temperature temp2 = new Temperature(temp0K.getTemperatureValueIn(TemperatureUnit.FAHRENHEIT), TemperatureUnit.FAHRENHEIT);
		Temperature temp3 = new Temperature(temp2.getTemperatureValueIn(TemperatureUnit.CELSIUS), TemperatureUnit.CELSIUS);
		Temperature temp1 = new Temperature(temp3.getTemperatureValueIn(TemperatureUnit.KELVIN), TemperatureUnit.KELVIN);
		for(int count = 0; count < 2000; count++){
			temp2 = new Temperature(temp1.getTemperatureValueIn(TemperatureUnit.FAHRENHEIT), TemperatureUnit.FAHRENHEIT);
			temp3 = new Temperature(temp2.getTemperatureValueIn(TemperatureUnit.CELSIUS), TemperatureUnit.CELSIUS);
			temp1 = new Temperature(temp3.getTemperatureValueIn(TemperatureUnit.KELVIN), TemperatureUnit.KELVIN);
		}
		assertEquals(temp0K, temp1);
		assertEquals(temp0K, temp2);
		assertEquals(temp0K, temp3);
	}
	
	/**
	 * Testmethode voor het initialiseren van een temperatuur met waarde < absolute nulpunt
	 */
	@Test(expected=IllegalArgumentException.class) 
	public void lowerThanAbsoluteNul() throws Exception{
		new Temperature(new BigDecimal(BigInteger.valueOf(-27576),2),TemperatureUnit.CELSIUS);
	}
	
	@Test(expected=IllegalArgumentException.class) 
	public void scaleTooLarge() throws Exception{
		new Temperature(new BigDecimal(BigInteger.valueOf(67546148),3),TemperatureUnit.CELSIUS);
	}
	
	@Test
	public void compareToValid(){
		Temperature temp2000FInC = new Temperature(new BigDecimal(BigInteger.valueOf(109333),2), TemperatureUnit.CELSIUS);
		Temperature temp2000FInK = new Temperature(new BigDecimal(BigInteger.valueOf(136648),2), TemperatureUnit.KELVIN);
		assertEquals(temp2000F.compareTo(temp2000FInC), 0);
		assertEquals(temp2000F.compareTo(temp2000FInK), 0);
		assertEquals(temp2000F.compareTo(temp2000C), -1);
		assertEquals(temp2000F.compareTo(temp2000K), -1);
	}
	
	@Test (expected=IllegalArgumentException.class) 
	public void compareToInValid(){
		temp2000F.compareTo(null);
	}
}
